<template>
  <div>
    <a-select
        :loading="dataLoading01"
        :style="bodyStyle01"
        @select="handleSelect"
        showSearch
        allowClear
        :filter-option="filterOption"
        @popupScroll="handlePopupScroll"
        @search="handleSearch"
        v-model="renderedOptionsId01"
        :disabled="disabled"
        v-if="!isMultiple"
        @change="handleChange"
    >
      <a-select-option v-for="item in renderedOptions01" :key="item.id">
        {{item.code?item.name+'('+item.code+')':item.name}}
      </a-select-option>
    </a-select>
    <a-select
        mode="multiple"
        :maxTagTextLength="25"
        :maxTagCount="6"
        :loading="dataLoading01"
        :style="bodyStyle01"
        @popupScroll="handlePopupScroll"
        @search="handleSearch"
        v-model="renderedOptionsId02"
        v-if="isMultiple"
        showSearch
        :filter-option="filterOption"
        @change="handleSelect01"
    >
      <a-select-option v-for="item in renderedOptions01" :key="(item.id)">
        {{item.code?item.name+'('+item.code+')':item.name}}
      </a-select-option>
    </a-select>
  </div>
</template>

<script>
import debounce from 'lodash/debounce'
import {uniqueReduce} from "@/utils/util";
export default {
  name: "bigDataSelect",
  props: {
    type: {
      type: String,
      default: () => {
        return ''
      }
    },
    isMultiple: {
      type: Boolean,
      default: () => {
        return false
      }
    },
    bodyStyle: {
      type: Object,
      default: () => {
        return {}
      }
    },
    dataLoading: {
      type: Boolean,
      default: () => {
        return false
      }
    },
    renderedOptions: {
      type: Array,
      default: () => {
        return []
      }
    },
    renderedOptionsId: {
      type: Number,
      default: () => {
        return undefined
      }
    },
    renderedOptionsIdList: {
      type: Array,
      default: () => {
        return []
      }
    },
    LOAD_NUM: {
      type: Number,
      default: () => {
        return 100
      }
    },
    searchVal: {
      type: String,
      default: () => {
        return ''
      }
    },
    originalList: {
      type: Array,
      default: () => {
        return []
      }
    },
    filterDataList:{
      type: Array,
      default: () => {
        return []
      }
    },
    disabled: {
      type: Boolean,
      default: () => {
        return false
      }
    },
  },
  data () {
    return {
      bodyStyle01: this.bodyStyle,
      type01: this.type,
      dataLoading01: this.dataLoading,
      renderedOptions01: this.renderedOptions,
      renderedOptionsId01: this.renderedOptionsId,
      renderedOptionsId02: this.renderedOptionsIdList,
      LOAD_NUM01: this.LOAD_NUM,
      searchVal01: this.searchVal,
      originalList01: this.originalList,
      filterDataList01: this.filterDataList,
      isMultiple01: this.isMultiple,
      disabled01: this.disabled
    }
  },
  watch: {
    isMultiple: {handler (newVal) {this.isMultiple01 = newVal}, deep: true, immediate: true},
    disabled: {handler (newVal) {this.disabled01 = newVal}, deep: true, immediate: true},
    bodyStyle: {handler (newVal) {this.bodyStyle01 = newVal}, deep: true, immediate: true},
    type: {handler (newVal) {this.type01 = newVal}, deep: true, immediate: true},
    dataLoading: {handler (newVal) {this.dataLoading01 = newVal}, deep: true, immediate: true},
    renderedOptions: {handler (newVal) {this.renderedOptions01 = newVal}, deep: true, immediate: true},
    renderedOptionsId: {handler (newVal) {this.renderedOptionsId01 = newVal}, deep: true, immediate: true},
    renderedOptionsIdList: {handler (newVal) {this.renderedOptionsId02 = newVal;if(newVal.length<=0){this.handleSearch()}}, deep: true, immediate: true},
    LOAD_NUM: {handler (newVal) {this.LOAD_NUM01 = newVal}, deep: true, immediate: true},
    searchVal: {handler (newVal) {this.searchVal01 = newVal}, deep: true, immediate: true},
    originalList: {handler (newVal) {this.originalList01 = newVal}, deep: true, immediate: true},
    filterDataList: {handler (newVal) {this.filterDataList01 = newVal}, deep: true, immediate: true},
  },
  methods: {
    // 文本框值变化时触发 -- 从数据源中过滤出含搜索内容的数据，并取过滤结果的前n条作为下拉列表的可选项
    handleSearch(val) {
      this.searchVal01 = val
      this.$emit('changebigSelect', {searchVal:this.searchVal01, type: this.type01})
      let filterList = []
      if (val) {
        filterList = (this.originalList01).filter(item => {
          if (item.code && (item.code.indexOf(val) > -1 || item.name.indexOf(val) > -1)) {
            return item
          } else if (!item.code && (item.name.indexOf(val) > -1)) {
            return item
          }
        })
      } else if (this.renderedOptionsId01) {
        const defaultStaff = this.originalList01.filter(item => item.id === this.renderedOptionsId01)
        const otherStaff = this.originalList01.filter(item => item.id !== this.renderedOptionsId01)
        filterList = defaultStaff.concat(otherStaff)
      } else {
        filterList = this.originalList01
      }
      this.filterDataList01 = filterList
      this.renderedOptions01 = filterList.length < this.LOAD_NUM01 ? filterList : filterList.slice(0, this.LOAD_NUM01)
      this.renderedOptions01 = uniqueReduce(this.renderedOptions01, ['id'])
      this.$emit('changebigSelect', {filterDataList:this.filterDataList01, renderedOptions:this.renderedOptions01, type: this.type01})
    },
    // 滚动时触发（防止抖动）
    handlePopupScroll: debounce(function () {
      if (this.searchVal01 === '') {
        this.loadMoreData(this.originalList01)
      } else {
        this.loadMoreData(this.filterDataList01)
      }
    }, 400),
    // 加载更多数据到select框
    loadMoreData(dataList) {
      const renderedLen = this.renderedOptions01.length // 已渲染的下拉列表长度
      const totalLen = dataList.length // 当前数据源的长度
      let addList = []
      if (renderedLen < totalLen) {
        if (renderedLen + this.LOAD_NUM01 <= totalLen) {
          addList = dataList.slice(renderedLen, renderedLen + this.LOAD_NUM01)
        } else {
          addList = dataList.slice(renderedLen, renderedLen + (totalLen % this.LOAD_NUM01))
        }
        this.renderedOptions01 = (this.renderedOptions01).concat(addList)
        this.renderedOptions01 = uniqueReduce(this.renderedOptions01, ['id'])
        this.$emit('changebigSelect', {renderedOptions: this.renderedOptions01, type: this.type01})
      }
    },
    handleChange(val) {
      if(!val){this.$emit('changebigSelect', {renderedOptionsId: val, type: this.type01, clear: 1})}
    },
    handleSelect01(val) {
      this.$emit('changebigSelect', {renderedOptionsIdList: val, type: this.type01})
    },
    // 被选中时调用，参数为选中项的 value (或 key) 值
    handleSelect(val) {
      this.$emit('changebigSelect', {renderedOptionsId: val, type: this.type01})
      if (this.searchVal01) {
        const selectedArr = (this.originalList01).filter(item => item.id === val) // 从数据源中过滤出下拉框选中的值，并返回一个数组
        const restList = (this.originalList01).filter(item => item.id !== val) // 从数据源中过滤出其他的值，返回一个数组
        const newList = selectedArr.concat(restList).slice(0, this.LOAD_NUM01) // 将选中的元素放到下拉列表的第一位
        this.renderedOptions01 = newList // 更新已渲染的下拉列表
        this.originalList01 = selectedArr.concat(restList) // 更新数据源
        this.searchVal01 = '' // 因为触发handleSelect函数时，会自动清空用户输入的内容。因此，searchVal需要重置。
        this.$emit('changebigSelect', {renderedOptions: this.renderedOptions01, originalList: this.originalList01, searchVal: this.searchVal01, type: this.type01})
      }
    },
    // 输入框筛选
    filterOption(input, option){
      return (
        option.componentOptions.children[0].text.toUpperCase().indexOf(input.toUpperCase()) >= 0
      );
    }
  }
}
</script>

<style scoped>
/deep/ .ant-select-disabled .ant-select-selection {
  background-color: #fff;
}
</style>